<template>
  <el-upload
    :file-list="fileList"
    @update:file-list="updateFileList"
    :multiple="true"
    :drag="true"
    :accept="accept"
    :show-file-list="showFileList"
    :list-type="'text'"
    :auto-upload="true"
    :limit="limit"
    :on-preview="preview"
    :on-remove="remove"
    :on-success="success"
    :on-error="error"
    :on-progress="progress"
    :on-change="change"
    :on-exceed="exceed"
    :before-upload="beforeUpload"
    :before-remove="beforeRemove"
    :http-request="httpRequest"
  >
    <slot>
      <el-icon class="el-icon--upload">
        <upload-filled />
      </el-icon>
      <div class="el-upload__text">拖动文件到这里或<em>点击上传</em></div>
    </slot>
    <template #tip>
      <slot name="tip">
        <div class="el-upload__tip">上传过程中无法取消</div>
      </slot>
    </template>
    <template #file="{ file }">
      <slot name="file" :file="file"> </slot>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { UploadRequestOptions, UploadUserFile } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { fileApi } from '@/api/file'

interface Props {
  modelValue?: any
  accept?: string
  limit?: number
  showFileList?: boolean //是否显示上传的文件列表
  preview?: Function //点击文件列表中已上传的文件时的钩子，用于预览
  remove?: Function //文件列表移除文件时的钩子
  success?: Function //文件上传成功时的钩子
  error?: Function //文件上传失败时的钩子
  progress?: Function //文件上传时的钩子
  change?: Function //文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
  exceed?: Function //当超出限制时，执行的钩子函数
  beforeUpload?: Function //上传文件之前的钩子，参数为上传的文件， 若返回false或者返回 Promise 且被 reject，则停止上传
  beforeRemove?: Function //删除文件之前的钩子，参数为上传的文件和文件列表， 若返回 false 或者返回 Promise 且被 reject，则停止删除。
}

const emit = defineEmits(['update:modelValue'])
const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  showFileList: true
})
const fileList = ref<UploadUserFile[]>(props.modelValue)
//根据Promise状态确定上传成功或失败
const httpRequest = (options: UploadRequestOptions): XMLHttpRequest | Promise<unknown> => {
  return fileApi.uploadFile(options.file, options.onProgress)
}
const updateFileList = (files: UploadUserFile[]) => {
  fileList.value = files
  emit('update:modelValue', files)
}
</script>
<style scoped lang="scss"></style>
